<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="baidu-site-verification" content="SCzNOI2Wq6" />
    <meta name="renderer" content="webkit">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <title>
        daozhuang
    </title>
    
<link rel="stylesheet" href="/libs/highlight/styles/monokai-sublime.css">

    
<link rel="stylesheet" href="/libs/font-awesome/css/font-awesome.min.css">

    
<link rel="stylesheet" href="/css/style.css">

<meta name="generator" content="Hexo 4.2.1"></head>

<body id="bodyx">
    <div class="hd posts">
    <a href="/index.html"><i class="fa fa-reply replay-btn" aria-hidden="true"></i></a>
    <div class="post-title">
        <p>
            Docker安装、自定义镜像、网络配置、持久化数据、compose、swarm
        </p>
        <hr>
    </div>
    <div class="post-content">
        <h2 id="Docker简介"><a href="#Docker简介" class="headerlink" title="Docker简介"></a>Docker简介</h2><p>Docker是一个开源的引擎，它提供了为应用程序创建轻量级/可移植/高效的容器方案。支持部署到本地和云平台环境。使用Docker有很多好处,比如更快的交付和部署，更高效的资源利用，更轻松的迁移。它的应用场景包括Web应用的自动化打包部署,自动化测试,持续集成等。</p>
<h4 id="Docker基本概念"><a href="#Docker基本概念" class="headerlink" title="Docker基本概念"></a>Docker基本概念</h4><p>docker的核心：   <strong><em>镜像、容器、仓库</em></strong></p>
<h6 id="镜像"><a href="#镜像" class="headerlink" title="镜像"></a>镜像</h6><p>Docker中的镜像类似于虚拟机的镜像，可以理解为一个只读的模板。比如，一个镜像包含一个基本操作系统环境，或者包含某个应用程序正确运行所需的运行环境。镜像是创建Docker容器的基础，通过镜像的版本控制，Docker提供了十分简单的机制来创建和更新镜像，也可以直接下载已经做好的应用镜像，并直接使用。</p>
<h6 id="容器"><a href="#容器" class="headerlink" title="容器"></a>容器</h6><p>Docker容器类似一个轻量级的沙盒，Docker利用容器来运行和隔离应用，容器是从镜像创建的应用运行示例，可以对它进行启动，停止，删除等操作。<br>可以理解容器为一个简易版的Linux操作系统环境，包括某些应用程序打包而成的盒子。</p>
<h6 id="仓库"><a href="#仓库" class="headerlink" title="仓库"></a>仓库</h6><p>Docker仓库类似代码仓库，是Docker用来集中存放镜像的地方。Docker仓库根据镜像是否公开分为公开仓库和私有仓库，目前最大的公开仓库是官方提供的Docker Hub,其中存放了大量的镜像供用户下载。同时，国内不少云服务提供商也提供了仓库的本地源，可以提高稳定的国内访问。</p>
<p>关于私有仓库，用户可以自行搭建本地仓库，用于维护私有的镜像。</p>
<h6 id="分层存储"><a href="#分层存储" class="headerlink" title="分层存储"></a>分层存储</h6><p>镜像构建时，会一层一层的构建，前一层是后一层的基础，每一层构建完就不会发生改变，后一层所有的改变都不会影响前一层的。比如删除前一层的文件，其实并不是删除了前一层的文件，只是标记为已删除，在容器运行的时候，不会看到这个文件,但是实际上文件还存在。</p>
<p>分层存储的特征让镜像的复用变得容易，比如可以以之前建好的镜像作为基础层,然后逐步添加新的层，以定制自己所需的内容。</p>
<h2 id="Docker的安装"><a href="#Docker的安装" class="headerlink" title="Docker的安装"></a>Docker的安装</h2><p>删除旧版本的 Docker</p>
<figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">sudo yum remove docker \</span><br><span class="line">                  docker<span class="literal">-client</span> \</span><br><span class="line">                  docker<span class="literal">-client</span><span class="literal">-latest</span> \</span><br><span class="line">                  docker<span class="literal">-common</span> \</span><br><span class="line">                  docker<span class="literal">-latest</span> \</span><br><span class="line">                  docker<span class="literal">-latest</span><span class="literal">-logrotate</span> \</span><br><span class="line">                  docker<span class="literal">-logrotate</span> \</span><br><span class="line">                  docker<span class="literal">-engine</span></span><br></pre></td></tr></table></figure>
<p>安装所需的软件包</p>
<figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">sudo yum install <span class="literal">-y</span> yum<span class="literal">-utils</span> \</span><br><span class="line">  device<span class="literal">-mapper</span><span class="literal">-persistent</span><span class="literal">-data</span> \</span><br><span class="line">  lvm2</span><br></pre></td></tr></table></figure>
<p>设置docker默认的镜像仓库</p>
<figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">sudo yum<span class="literal">-config</span><span class="literal">-manager</span> \</span><br><span class="line">    -<span class="literal">-add</span><span class="literal">-repo</span> \</span><br><span class="line">    https://download.docker.com/linux/centos/docker<span class="literal">-ce</span>.repo</span><br></pre></td></tr></table></figure>
<p>安装docker</p>
<figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo yum install docker<span class="literal">-ce</span> docker<span class="literal">-ce</span><span class="literal">-cli</span> containerd.io</span><br></pre></td></tr></table></figure>
<p>启动docker</p>
<figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo systemctl start docker</span><br></pre></td></tr></table></figure>
<p>以下代码是设置阿里云的 docker 镜像仓库</p>
<figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">sudo mkdir <span class="literal">-p</span> /etc/docker</span><br><span class="line">sudo tee /etc/docker/daemon.json &lt;&lt;-<span class="string">'EOF'</span></span><br><span class="line">&#123;</span><br><span class="line">  <span class="string">"registry-mirrors"</span>: [<span class="string">"https://y5j5hcnv.mirror.aliyuncs.com"</span>]</span><br><span class="line">&#125;</span><br><span class="line">EOF</span><br><span class="line">sudo systemctl daemon<span class="literal">-reload</span></span><br><span class="line">sudo systemctl restart docker</span><br></pre></td></tr></table></figure>
<h4 id="docker常用命令"><a href="#docker常用命令" class="headerlink" title="docker常用命令"></a>docker常用命令</h4><figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">docker images 										<span class="comment"># 查看所有模板</span></span><br><span class="line">docker pull tomcat 									<span class="comment"># 从远程仓库拉取 image 镜像</span></span><br><span class="line">docker rmi tomcat									<span class="comment"># 删除某个镜像</span></span><br><span class="line">docker run <span class="literal">-d</span> -<span class="literal">-name</span> mytomcat <span class="literal">-p</span> <span class="number">80</span>:<span class="number">8080</span> tomcat 	<span class="comment"># 运行docker image 镜像</span></span><br><span class="line">docker exec <span class="literal">-it</span> tomcat /bin/bash					<span class="comment"># 进入到容器中执行命令</span></span><br><span class="line">docker ps 											<span class="comment"># 查看正在运行的  container</span></span><br><span class="line">docker kill tomcat 									<span class="comment"># 杀死进程</span></span><br><span class="line">docker build <span class="literal">-t</span> vitshop<span class="literal">-image</span>   					<span class="comment"># 构建 image 镜像</span></span><br><span class="line">docker logs <span class="operator">-f</span> vitshop								<span class="comment"># 查看日志</span></span><br><span class="line">docker container ls <span class="literal">-a</span> 								<span class="comment"># 查看所有的container</span></span><br><span class="line">docker container rm tomcat 							<span class="comment"># 删除container</span></span><br><span class="line">docker inspect tomcat								<span class="comment"># 查看 image 镜像详细信息</span></span><br><span class="line">docker history tomcat								<span class="comment"># 查看镜像历史</span></span><br><span class="line">docker volume ls									<span class="comment"># 查看所有的 volume</span></span><br><span class="line">docker volume inspect tomcat						<span class="comment"># 查看 volume 详情</span></span><br><span class="line">docker volume create								<span class="comment"># 创建volume</span></span><br><span class="line">docker volume rm									<span class="comment"># 删除 volume</span></span><br><span class="line">docker start mytomcat								<span class="comment"># 启动已有的container</span></span><br></pre></td></tr></table></figure>
<p><a href="https://docs.docker.com/reference/" target="_blank" rel="noopener">docker官网命令集合</a></p>
<h2 id="Docker-自定义image-自定义docker镜像"><a href="#Docker-自定义image-自定义docker镜像" class="headerlink" title="Docker | 自定义image 自定义docker镜像"></a>Docker | 自定义image 自定义docker镜像</h2><h6 id="Dockerfile-什么是-Dockerfile？"><a href="#Dockerfile-什么是-Dockerfile？" class="headerlink" title="Dockerfile  什么是 Dockerfile？"></a>Dockerfile  什么是 Dockerfile？</h6><p>Dockerfile是一个用来构建镜像的文本文件，文本内容包含了一条条构建镜像所需的指令和说明。</p>
<h4 id="Dockerfile-指令的作用"><a href="#Dockerfile-指令的作用" class="headerlink" title="Dockerfile 指令的作用"></a>Dockerfile 指令的作用</h4><figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line">FROM centos		<span class="comment"># 基于什么镜像之上构建自己的自定义镜像</span></span><br><span class="line">RUN				<span class="comment"># 用于执行后面命令，RUN ["./test.php", "dev", "offline"] 等价于 RUN ./test.php dev offline</span></span><br><span class="line">CMD				<span class="comment"># 类似于 RUN 命令，用于运行程序。 CMD在docker run 时运行。 run 是在docker build时运行</span></span><br><span class="line">COPY 			<span class="comment"># 复制指令，从上下文目录中复制文件或者目录到容器的制定位置</span></span><br><span class="line">ADD				<span class="comment"># 跟复制命令使用格式一致（同样的需求下，官方建议使用 copy）</span></span><br><span class="line">VOLUME			<span class="comment"># 定义匿名数据卷。在启动容器时忘记挂载数据卷，会自动挂载匿名的数据卷。   做持久化数据</span></span><br><span class="line"></span><br><span class="line">ENTRYPOINT		<span class="comment"># 类似于 cmd 命令但其不会被 docker run的命令行参数指定的指令所覆盖，而且这些命令行的参数会被当做参数传给 </span></span><br><span class="line">				<span class="comment"># ENTRYPOINT 所指定的程序，但是如果运行 docker run 时候使用了 --entrypoint 选项，</span></span><br><span class="line">				<span class="comment"># 此选项的参数可当做要运行的程序覆盖 ENTRYPOINT 指定的程序</span></span><br><span class="line">				<span class="comment"># 优点： 在执行 docker run 的时候可以指定 ENTRYPOINT 运行所需的参数</span></span><br><span class="line">				<span class="comment"># 注意： 如果 Dockerfile 文件中存在多个 ENTRYPOINT 指令，仅最后一个生效。</span></span><br><span class="line"></span><br><span class="line">ENV				<span class="comment"># 设置环境变量，定义了环境变量，那么在后续的指令中就可以使用这个变量。</span></span><br><span class="line"></span><br><span class="line">ARG				<span class="comment"># 构建参数，与 ENV 作用一至。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效，</span></span><br><span class="line">				<span class="comment"># 也就是说只有 docker build 的过程中有效，构建好的镜像内不存在此环境变量。</span></span><br><span class="line">				<span class="comment"># 构建命令 docker build 中可以用 --build-arg &lt;参数名&gt;=&lt;值&gt; 来覆盖。</span></span><br><span class="line"></span><br><span class="line">EXPOSE			<span class="comment"># 仅仅只是声明端口。帮助镜像使用者理解这个镜像服务的守护端口，以方便配置映射。</span></span><br><span class="line">				<span class="comment"># 在运行时使用随机端口映射时，也就是 docker run -P 时，会自动随机映射 EXPOSE 的端口。</span></span><br><span class="line"></span><br><span class="line">WORKDIR			<span class="comment"># 指定工作目录。用 WORKDIR 指定的工作目录，会在构建镜像的每一层中都存在（WORKDIR 指定的工作目录，必须是提前创建好的）</span></span><br><span class="line">				<span class="comment"># docker build 构建镜像过程中的，每一个 RUN 命令都是新建的一层。只有通过 WORKDIR 创建的目录才会一直存在。</span></span><br><span class="line"></span><br><span class="line">USER			<span class="comment"># 用于指定执行后续命令的用户和用户组，这边只是切换后续命令执行的用户（用户和用户组必须提前已经存在）。</span></span><br><span class="line">HEALTHCHECK		<span class="comment"># 用于指定某个程序或者指令来监控 docker 容器服务的运行状态。</span></span><br><span class="line">ONBUILD			<span class="comment"># 用于延迟构建命令的执行。简单的说，就是 Dockerfile 里用 ONBUILD 指定的命令，在本次构建镜像的过程中不会执行</span></span><br><span class="line">				<span class="comment"># （假设镜像为 test-build）。当有新的 Dockerfile 使用了之前构建的镜像 FROM test-build ，</span></span><br><span class="line">				<span class="comment"># 这是执行新镜像的 Dockerfile 构建时候，会执行 test-build 的 Dockerfile 里的 ONBUILD 指定的命令。</span></span><br></pre></td></tr></table></figure>

<h4 id="使用-Dockerfile-创建自定义-image-镜像"><a href="#使用-Dockerfile-创建自定义-image-镜像" class="headerlink" title="使用 Dockerfile 创建自定义 image 镜像"></a>使用 Dockerfile 创建自定义 image 镜像</h4><p>以springboot项目为例：把打包好的   springboot.jar  放入服务器自定义目录中，并创建 Dockerfile 文件。</p>
<figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">mkdir vitshop<span class="literal">-image</span>  <span class="comment"># 创建自定义目录，</span></span><br><span class="line">vim Dockerfile       <span class="comment"># 创建 Dockerfile 文件</span></span><br></pre></td></tr></table></figure>
<p><strong>编辑 Dockerfile 文件</strong></p>
<figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">FROM openjdk:<span class="number">8</span></span><br><span class="line">MAINTAINER itcrazy2016</span><br><span class="line">LABEL name=<span class="string">"dockerfile-dome"</span> version=<span class="string">"1.0"</span> author=<span class="string">"itcrazy2016"</span></span><br><span class="line">COPY vitshop<span class="literal">-0</span>.<span class="number">0.1</span>.jar vitshop.jar</span><br><span class="line">CMD [<span class="string">"java"</span>,<span class="string">"-jar"</span>,<span class="string">"vitshop.jar"</span>]</span><br></pre></td></tr></table></figure>
<p>保存 Dockerfile 文件之后，使用   docker build -t vitshop-image  命令创建  image。<br>等待创建完毕之后就可以，运行或者查看 image 镜像了。</p>
<figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">docker build <span class="literal">-t</span> vitshop<span class="literal">-image</span> .   						<span class="comment"># -t vitshop-image 是自定义的名称</span></span><br><span class="line">docker iamges 											<span class="comment"># 查看所有的镜像</span></span><br><span class="line">docker run <span class="literal">-d</span> -<span class="literal">-name</span> vitshop <span class="literal">-p</span> <span class="number">80</span>:<span class="number">8080</span> vitshop<span class="literal">-image</span>	<span class="comment"># 运行自己创建的  image镜像</span></span><br></pre></td></tr></table></figure>
<h4 id="把-image-镜像推送到阿里云镜像仓库"><a href="#把-image-镜像推送到阿里云镜像仓库" class="headerlink" title="把 image 镜像推送到阿里云镜像仓库"></a>把 image 镜像推送到阿里云镜像仓库</h4><p>** 登陆阿里云控制台，找到容器镜像服务标签，选择下面的镜像仓库开通空间之后照下面命令上传自己的镜像。 **</p>
<figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 登陆到阿里云镜像仓库</span></span><br><span class="line"><span class="variable">$</span> sudo docker login -<span class="literal">-username</span>=tb4005142_00 registry.cn<span class="literal">-beijing</span>.aliyuncs.com</span><br><span class="line"><span class="comment"># 给自定的镜像打包</span></span><br><span class="line"><span class="variable">$</span> sudo docker tag [<span class="type">ImageId</span>] registry.cn<span class="literal">-beijing</span>.aliyuncs.com/daozhuang/daozhuang:[镜像版本号]</span><br><span class="line"><span class="comment"># 推送到阿里云仓库</span></span><br><span class="line"><span class="variable">$</span> sudo docker push registry.cn<span class="literal">-beijing</span>.aliyuncs.com/daozhuang/daozhuang:[镜像版本号]</span><br><span class="line"><span class="comment"># 从Registry中拉取镜像</span></span><br><span class="line"><span class="variable">$</span> sudo docker pull registry.cn<span class="literal">-beijing</span>.aliyuncs.com/daozhuang/daozhuang:[镜像版本号]</span><br><span class="line"><span class="comment"># 从ECS推送镜像时，可以选择使用镜像仓库内网地址。推送速度将得到提升并且将不会损耗您的公网流量。</span></span><br><span class="line"><span class="comment"># 如果您使用的机器位于VPC网络，请使用 registry-vpc.cn-beijing.aliyuncs.com 作为Registry的域名登录，并作为镜像命名空间前缀。</span></span><br></pre></td></tr></table></figure>
<h4 id="深入探讨Container"><a href="#深入探讨Container" class="headerlink" title="深入探讨Container"></a>深入探讨Container</h4><p><strong>Docker commit 命令</strong><br>docker commit :从容器创建一个新的镜像。<br><strong>语法：</strong></p>
<figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">docker commit [<span class="type">OPTIONS</span>] CONTAINER [<span class="type">REPOSITORY</span>[:<span class="type">TAG</span>]]</span><br><span class="line">docker commit <span class="literal">-a</span> <span class="string">"xxxx"</span> <span class="literal">-m</span> <span class="string">"xxxx"</span> a404c6c174a2  mymysql:v1</span><br></pre></td></tr></table></figure>
<p><strong>OPTIONS说明：</strong><br>                                    -a :提交的镜像作者；<br>                                    -c :使用Dockerfile指令来创建镜像；<br>                                    -m :提交时的说明文字；<br>                                    -p :在commit时，将容器暂停。</p>
<h4 id="container资源限制"><a href="#container资源限制" class="headerlink" title="container资源限制"></a>container资源限制</h4><p><strong>语法：</strong></p>
<figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">docker run [<span class="type">OPTIONS</span>] IMAGE [<span class="type">COMMAND</span>] [<span class="type">ARG...</span>]</span><br><span class="line">docker run -<span class="literal">-name</span> mynginx <span class="literal">-d</span> nginx:latest</span><br><span class="line"><span class="comment"># 内存限制</span></span><br><span class="line">docker run <span class="literal">-d</span> -<span class="literal">-memory</span> <span class="number">100</span>M -<span class="literal">-name</span> tomcat01 tomcat</span><br><span class="line"><span class="comment"># cpu限制  设置CPU权重</span></span><br><span class="line">docker run <span class="literal">-d</span> -<span class="literal">-cpu</span><span class="literal">-shares</span> <span class="number">10</span> -<span class="literal">-name</span> tomcat01 tomcat</span><br></pre></td></tr></table></figure>
<p><strong>OPTIONS说明：</strong><br>-a stdin: 指定标准输入输出内容类型，可选 STDIN/STDOUT/STDERR 三项；<br>-d: 后台运行容器，并返回容器ID；<br>-i: 以交互模式运行容器，通常与 -t 同时使用；<br>-P: 随机端口映射，容器内部端口随机映射到主机的高端口<br>-p: 指定端口映射，格式为：主机(宿主)端口:容器端口<br>-t: 为容器重新分配一个伪输入终端，通常与 -i 同时使用；<br>–name=”nginx-lb”: 为容器指定一个名称；<br>–dns 8.8.8.8: 指定容器使用的DNS服务器，默认和宿主一致；<br>–dns-search example.com: 指定容器DNS搜索域名，默认和宿主一致；<br>-h “mars”: 指定容器的hostname；<br>-e username=”ritchie”: 设置环境变量；<br>–env-file=[]: 从指定文件读入环境变量；<br>–cpuset=”0-2” or –cpuset=”0,1,2”: 绑定容器到指定CPU运行；<br>-m :设置容器使用内存最大值；<br>–net=”bridge”: 指定容器的网络连接类型，支持 bridge/host/none/container: 四种类型；<br>–link=[]: 添加链接到另一个容器；<br>–expose=[]: 开放一个端口或一组端口；<br>–volume , -v:    绑定一个卷</p>
<h2 id="Docker-容器网络配置"><a href="#Docker-容器网络配置" class="headerlink" title="Docker | 容器网络配置"></a>Docker | 容器网络配置</h2><h4 id="Docker的四种网络模式"><a href="#Docker的四种网络模式" class="headerlink" title="Docker的四种网络模式"></a>Docker的四种网络模式</h4><p><strong>docker默认网路 bridge</strong><br>Docker启动的时候会在主机上自动创建一个docker0网桥，实际上是一个Linux网桥，所有容器的启动如果在docker run的时候没有指定网络模式的情况下都会挂载到docker0网桥上。这样容器就可以和主机甚至是其他容器之间通讯了。<br>我们可以使用  命令   ip  a  查看所有的网卡</p>
<p><strong>host模式网络</strong><br>该模式中将禁用Docker容器的网络隔离，容器共享宿主机的网络命名空间，直接暴露在公网中，容器会继承宿主机的IP地址。使用host模式会将容器直接暴露在公网，会存在安全隐患。</p>
<p><strong>container模式网络</strong><br>该模式中，容器会使用另一个容器的网络命名空间。使用方式为:–net=container:containername</p>
<p><strong>none模式网络</strong><br>该模式将容器放置在自己的网络栈中，并不进行任何配置，该模式实际上是关闭了容器的网络功能。</p>
<p><strong>外部访问容器：</strong><br>外部要访问容器使用： -p 参数把容器端口映射到宿主机上即可访问，-p 和 -P是有区别的 -P是随机映射端口范围是 49000~49900；<br>-p是要自己指定端口号， 如：-p hostPort:containerPort </p>
<p><strong>容器访问外部：</strong><br>默认情况下，容器可以访问到外部网络的连接，因为容器的默认网络接口为docker0网桥上的接口，也即是主机上的本地接口。其原理是通过Linux系统的转发功能实现的，在Linux中检查转发是否打开：</p>
<figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">[<span class="type">root</span>@<span class="type">VM_0_14_centos</span> ~]<span class="comment"># sysctl net.ipv4.ip_forward=1</span></span><br><span class="line">net.ipv4.ip_forward = <span class="number">1</span></span><br></pre></td></tr></table></figure>
<p>0表示转发未打开，1表示转发已经打开。可以在docker run时使用–ip-forward=true来指定，Docker会打开主机的转发功能。</p>
<p>同时可以通过上述的nat表中找到对应的规则，在POSTRONTING的第一个规则就是把所有原地址在172.17.0.0/16网段但不是属于Docker0的网包(即容器中的网包)，动态伪装为0.0.0.0/0网段，即主机网卡。</p>
<h6 id="自定义-bridge-网络"><a href="#自定义-bridge-网络" class="headerlink" title="自定义 bridge 网络"></a>自定义 bridge 网络</h6><p>docker默认的网络模式<br>在使用此网络模式的时候需要端口映射，<br><strong>Docker网络操作：</strong></p>
<figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 创建网路</span></span><br><span class="line">docker network create <span class="literal">-d</span> bridge -<span class="literal">-subnet</span> <span class="number">172.25</span>.<span class="number">0.0</span>/<span class="number">16</span> mynet</span><br><span class="line"><span class="comment"># 连接一个网络到容器中</span></span><br><span class="line">docker network connect [<span class="type">OPTIONS</span>] NETWORK CONTAINER</span><br><span class="line">docker network connect mynet containername</span><br><span class="line"><span class="comment"># 查看所有网络</span></span><br><span class="line">docker network ls</span><br><span class="line"><span class="comment"># 删除网络</span></span><br><span class="line">docker network rm</span><br><span class="line"><span class="comment"># 容器和网络断开连接</span></span><br><span class="line">docker network disconnect [<span class="type">OPTIONS</span>] NETWORK CONTAINER</span><br><span class="line"><span class="comment"># 查看网络详情</span></span><br><span class="line">docker network inspect</span><br></pre></td></tr></table></figure>
<h4 id="Docker-link方式互联"><a href="#Docker-link方式互联" class="headerlink" title="Docker link方式互联"></a>Docker link方式互联</h4><p>容器之间相互通讯可以通过docker run中的–link=container_name:alias参数来达到效果。<br>此种方式可以很方便让容器使用容器名进行通讯，而不需要依赖ip地址，不过link方式仅仅解决了单机容器间的互联，多机的情况下，需要通过别的方式进行连接。</p>
<h2 id="Docker-持久化数据"><a href="#Docker-持久化数据" class="headerlink" title="Docker 持久化数据"></a>Docker 持久化数据</h2><h4 id="Docker文件系统"><a href="#Docker文件系统" class="headerlink" title="Docker文件系统"></a>Docker文件系统</h4><p>Docker的镜像是由多个文件系统(只读)叠加而成，当我们启动一个容器的时候，Docker会加载只读镜像层并在其上添加一层’读写层’.如果运行中的容器需要了一个文件，那么并不会修改只读层的文件，只会把该文件复制到’读写层’然后对他修改，只读层的文件就被隐藏了，当删除了Docker容器之后，或者重启容器之后，之前对文件的更改会丢失，镜像的只读层以及容器运行时的’读写层’被称为Union File System(联合文件系统)</p>
<p>为了能够保存数据的持久化以及共享容器之间的数据，提出了Volume的概念。简单来说Volume就是一个文件或者目录。它可以绕过联合文件系统，以正常的文件或者目录的形式保存在主机上。可以通过两种方式来初始化Volume,这两种方式有一些细微区别。</p>
<p><strong>运行时创建 volume</strong></p>
<figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 使用 -v 参数指定挂载的目录  声明volume</span></span><br><span class="line"><span class="comment"># 以下命令会创建一个CentOs的容器并且把容器内部的/data目录作为数据卷挂载</span></span><br><span class="line">docker run <span class="literal">-it</span> -<span class="literal">-name</span> centOs <span class="literal">-v</span> /<span class="keyword">data</span> centos</span><br><span class="line"><span class="comment"># 查看挂载的volume，可以看到容器已经把/var/lob/docker/volumes/xxx/_data目录挂载到容器的/data目录了。</span></span><br><span class="line">docker inspect <span class="operator">-f</span> &#123;&#123;.Mounts&#125;&#125; centOs</span><br><span class="line">[&#123;<span class="type">volume</span> <span class="type">centOs</span> /<span class="type">var</span>/<span class="type">lib</span>/<span class="type">docker</span>/<span class="type">volumes</span>/<span class="type">XXXXX</span>/<span class="type">_data</span> /<span class="type">data</span> <span class="type">local</span>  <span class="type">true</span> &#125;]</span><br><span class="line"><span class="comment"># 该命令是将主机的/home/centos/data目录挂载到容器的/data目录。</span></span><br><span class="line">docker run <span class="literal">-it</span> -<span class="literal">-name</span> centOs <span class="literal">-v</span> /home/centos/<span class="keyword">data</span>:/<span class="keyword">data</span> centos</span><br></pre></td></tr></table></figure>
<p>另外值得注意的是，只要将主机的目录挂载到容器上，那改变就会立即生效。挂载目录不会将镜像的文件复制到Volume中，只会把主机中不存在的文件夹创建出来。</p>
<p><strong>数据共享</strong><br>如果要授权一个容器访问另一个容器的Volume，可以使用-volumes-from参数来执行docker run命令:</p>
<figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker run <span class="literal">-it</span> -<span class="literal">-name</span> centOs1 -<span class="literal">-volumes</span><span class="literal">-from</span> centOs centos</span><br></pre></td></tr></table></figure>
<p>不管容器是否正在运行，Volume都不会被删除。</p>
<h4 id="数据备份与恢复"><a href="#数据备份与恢复" class="headerlink" title="数据备份与恢复"></a>数据备份与恢复</h4><p>如果使用数据卷容器，想做备份和恢复就非常容易了。假设有较多的镜像从centOs中挂载了数据卷，那么备份与恢复只需针对centOs这个容器即可。</p>
<p><strong>备份</strong></p>
<figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker run -<span class="literal">-volumes</span><span class="literal">-from</span> centOs <span class="literal">-v</span> <span class="variable">$</span>(pwd):/backup -<span class="literal">-name</span> worker centos tar cvf /backup/backup.tar /<span class="keyword">data</span></span><br></pre></td></tr></table></figure>
<p>这个命令的意思是 将当前目录挂载到容器的/backup 目录，然后容器的工作就是压缩 /data的内容到 /back/backup.tar文件中。执行完之后就会看见在当前目录中生成了backup.tar文件</p>
<p><strong>恢复</strong></p>
<figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker run -<span class="literal">-volumes</span><span class="literal">-from</span> centOs <span class="literal">-v</span> <span class="variable">$</span>(pwd):/backup centos tar xvf /backup/backup.tar <span class="literal">-C</span> /<span class="keyword">data</span></span><br></pre></td></tr></table></figure>
<p><strong>删除数据卷</strong><br>Volume可以使用两种方式删除数据卷：</p>
<ul>
<li>使用docker rm -v命令，这个命令移除容器的同时也会移除数据卷 </li>
<li>使用docker run –rm这个命令会在容器退出时清除数据</li>
<li>docker volume ls 列出所有数据卷</li>
<li>docker volume prune 删除无用的数据卷<h2 id="Docker-Compose"><a href="#Docker-Compose" class="headerlink" title="Docker Compose"></a>Docker Compose</h2><h4 id="Compose-简介"><a href="#Compose-简介" class="headerlink" title="Compose 简介"></a>Compose 简介</h4>Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过 Compose，您可以使用 YML 文件来配置应用程序需要的所有服务。然后，使用一个命令，就可以从 YML 文件配置中创建并启动所有服务。</li>
</ul>
<h4 id="Compose-使用的三个步骤："><a href="#Compose-使用的三个步骤：" class="headerlink" title="Compose 使用的三个步骤："></a>Compose 使用的三个步骤：</h4><ul>
<li>使用 Dockerfile 定义应用程序的环境。</li>
<li>使用 docker-compose.yml 定义构成应用程序的服务，这样它们可以在隔离环境中一起运行。</li>
<li>最后，执行 docker-compose up 命令来启动并运行整个应用程序。<h4 id="Compose-安装"><a href="#Compose-安装" class="headerlink" title="Compose 安装"></a>Compose 安装</h4>Linux 上我们可以从 Github 上下载它的二进制包来使用，最新发行的版本地址：<a href="https://github.com/docker/compose/releases。" target="_blank" rel="noopener">https://github.com/docker/compose/releases。</a><br>运行以下命令以下载 Docker Compose 的当前稳定版本：要安装其他版本的 Compose，请替换 1.24.1。<figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">sudo curl <span class="literal">-L</span> <span class="string">"https://github.com/docker/compose/releases/download/1.24.1/docker-compose-<span class="variable">$</span>(uname -s)-<span class="variable">$</span>(uname -m)"</span> <span class="literal">-o</span> /usr/local/bin/docker<span class="literal">-compose</span></span><br><span class="line">sudo chmod +x /usr/local/bin/docker<span class="literal">-compose</span></span><br><span class="line">sudo ln <span class="literal">-s</span> /usr/local/bin/docker<span class="literal">-compose</span> /usr/bin/docker<span class="literal">-compose</span></span><br><span class="line">docker<span class="literal">-compose</span> -<span class="literal">-version</span></span><br></pre></td></tr></table></figure>
注意： 对于 alpine，需要以下依赖包： py-pip，python-dev，libffi-dev，openssl-dev，gcc，libc-dev，和 make。<h4 id="使用："><a href="#使用：" class="headerlink" title="使用："></a>使用：</h4><figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 创建一个测试目录：</span></span><br><span class="line">mkdir composetest</span><br><span class="line">cd composetest</span><br><span class="line"><span class="comment"># 在此文件夹中放置 需要运行的项目 如： springboot.jar，还有Dockerfile，和docker-compose.yml</span></span><br><span class="line">springboot.jar</span><br><span class="line">Dockerfile</span><br><span class="line">docker<span class="literal">-compose</span>.yml</span><br></pre></td></tr></table></figure>
docker-compose.yml 配置文件:<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># yaml 配置</span></span><br><span class="line"><span class="attr">version:</span> <span class="string">'3'</span>					<span class="comment"># 指定本 yml 依从的 compose 哪个版本制定的。</span></span><br><span class="line"><span class="attr">services:</span>						<span class="comment"># </span></span><br><span class="line">  <span class="attr">web:</span>							<span class="comment"># 该 web 服务使用从 Dockerfile 当前目录中构建的镜像。</span></span><br><span class="line">    <span class="attr">build:</span> <span class="string">.</span>					<span class="comment"># 指定为构建镜像上下文路径：也就是Dockerfile文件的路径</span></span><br><span class="line">    <span class="attr">networks:</span>					<span class="comment"># 指定容器连接的网络，使用顶级 networks 下的条目 。</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">app-net</span>					<span class="comment"># </span></span><br><span class="line">  <span class="attr">redis:</span>						<span class="comment"># </span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">"redis:alpine"</span>		<span class="comment"># 指定容器运行的镜像。</span></span><br><span class="line">    <span class="attr">networks:</span>					<span class="comment"># 指定容器连接的网络，使用顶级 networks 下的条目 。</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">app-net</span></span><br><span class="line"><span class="attr">networks:</span>						<span class="comment"># 配置网络 如果没有会自动创建</span></span><br><span class="line">  <span class="attr">app-net:</span></span><br><span class="line">    <span class="attr">driver:</span> <span class="string">bridge</span></span><br></pre></td></tr></table></figure>
使用 Compose 命令构建和运行您的应用：<figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 在测试目录中，执行以下命令来启动应用程序：</span></span><br><span class="line">docker<span class="literal">-compose</span> up</span><br><span class="line"><span class="comment"># 如果你想在后台执行该服务可以加上 -d 参数：</span></span><br><span class="line">docker<span class="literal">-compose</span> up <span class="literal">-d</span></span><br><span class="line"><span class="comment"># 若要对容器进行扩缩容</span></span><br><span class="line">docker<span class="literal">-compose</span> up -<span class="literal">-scale</span> web=<span class="number">5</span> <span class="literal">-d</span></span><br><span class="line">docker<span class="literal">-compose</span> ps</span><br><span class="line">docker<span class="literal">-compose</span> logs web</span><br></pre></td></tr></table></figure>
<h2 id="Swarm-集群管理"><a href="#Swarm-集群管理" class="headerlink" title="Swarm 集群管理"></a>Swarm 集群管理</h2><h4 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h4>Docker Swarm 是 Docker 的集群管理工具。它将 Docker 主机池转变为单个虚拟 Docker 主机。 Docker Swarm 提供了标准的 Docker API，所有任何已经与 Docker 守护程序通信的工具都可以使用 Swarm 轻松地扩展到多个主机。</li>
</ul>
<p>支持的工具包括但不限于以下各项：    Dokku、Docker Compose、Docker Machine、Jenkins</p>
<h4 id="原理"><a href="#原理" class="headerlink" title="原理"></a>原理</h4><p>如下图所示，swarm 集群由管理节点（manager）和工作节点（work node）构成。</p>
<ol>
<li>swarm mananger：负责整个集群的管理工作包括集群配置、服务管理等所有跟集群有关的工作。</li>
<li>work node：即图中的 available node，主要负责运行相应的服务来执行任务（task）。<br><img src="https://img-blog.csdnimg.cn/20191114152239754.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl8zNzg2NTMxMg==,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"><h4 id="搭建Swarm集群"><a href="#搭建Swarm集群" class="headerlink" title="搭建Swarm集群"></a>搭建Swarm集群</h4></li>
<li>进入manager： manager node也可以作为 worker node提供服务<figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker swarm init -<span class="literal">-advertise</span><span class="literal">-addr</span>=<span class="number">192.168</span>.<span class="number">0.11</span>		<span class="comment"># 这里的ip对应的是宿主机的ip</span></span><br></pre></td></tr></table></figure>
注意观察日志，拿到worker node加入manager node的信息<br><img src="https://img-blog.csdnimg.cn/20191114164331730.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl8zNzg2NTMxMg==,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"><ol start="2">
<li>进入两个worker 执行以下命令，加入到manager 集群中<figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">docker swarm join -<span class="literal">-token</span> SWMTKN<span class="literal">-1</span><span class="literal">-3zzim2k6p9v18ed2l94li2dngt10kvkibfa94gpjqvlt280y0f</span><span class="literal">-9gkawx7564dzh4fvmqccwhnyh</span> <span class="number">192.168</span>.<span class="number">0.48</span>:<span class="number">2377</span></span><br><span class="line"><span class="comment"># 日志打印</span></span><br><span class="line">This node joined a swarm as a worker.</span><br><span class="line"><span class="comment"># 进入到 manager node 查看所有node节点</span></span><br><span class="line">docker node ls</span><br><span class="line"><span class="comment"># 将 worker node 升级为 manager</span></span><br><span class="line">docker node promote NODENAME</span><br><span class="line"><span class="comment"># 将 manager node 降级为 worker</span></span><br><span class="line">docker node demote NODENAME</span><br><span class="line"><span class="comment"># 停止某个节点</span></span><br><span class="line">docker node update -<span class="literal">-availability</span> drain swarm<span class="literal">-worker1</span></span><br><span class="line"><span class="comment"># 从新启动某个节点</span></span><br><span class="line">docker node update -<span class="literal">-availability</span> active swarm<span class="literal">-worker1</span></span><br></pre></td></tr></table></figure></li>
</ol>
<strong>注意</strong>：swarm-worker1 状态变为 Drain。不会影响到集群的服务，只是 swarm-worker1 节点不再接收新的任务，集群的负载能力有所下降。<h4 id="Swarm基本操作"><a href="#Swarm基本操作" class="headerlink" title="Swarm基本操作"></a>Swarm基本操作</h4><figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 创建一个tomcat的service</span></span><br><span class="line">docker service create -<span class="literal">-name</span> my<span class="literal">-tomcat</span> tomcat</span><br><span class="line"><span class="comment"># 查看当前swarm的service</span></span><br><span class="line">docker service ls</span><br><span class="line"><span class="comment"># 查看service的启动日志</span></span><br><span class="line">docker service logs my<span class="literal">-tomcat</span></span><br><span class="line"><span class="comment"># 查看 service详情</span></span><br><span class="line">docker service inspect my<span class="literal">-tomcat</span></span><br><span class="line"><span class="comment"># 查看 my-tomcat 运行在哪个node上</span></span><br><span class="line">docker service ps my<span class="literal">-tomcat</span></span><br><span class="line"><span class="comment"># 水平扩展service</span></span><br><span class="line">docker service scale my<span class="literal">-tomcat</span>=<span class="number">5</span></span><br><span class="line"><span class="comment"># 查看所有service</span></span><br><span class="line">docker service ls</span><br><span class="line"><span class="comment"># 删除 service</span></span><br><span class="line">docker service rm my<span class="literal">-tomcat</span></span><br></pre></td></tr></table></figure>

</li>
</ol>
<p>参考文章 <a href="https://blog.csdn.net/u012943767/article/details/79767670" target="_blank" rel="noopener">https://blog.csdn.net/u012943767/article/details/79767670</a></p>

    </div>

    
        <hr class="fhr">
        <div id="vcomments"></div>
    
</div>
    <div class="footer" id="footer">
    <p>Copyright © 2020 <a class="flink" href="https://hexo.io" target="_blank" rel="noopener">Hexo</a>-<a class="flink" href="https://github.com/sanjinhub/hexo-theme-geek" target="_blank" rel="noopener">Geek</a>.
        <label class="el-switch el-switch-green el-switch-sm" style="vertical-align: sub;">
            <input type="checkbox" name="switch" id="update_style">
            <span class="el-switch-style"></span>
        </label>
<!--         <script type="text/javascript">
        var cnzz_protocol = (("https:" == document.location.protocol) ? "https://" : "http://");
        document.write(unescape("%3Cspan id='cnzz_stat_icon_1278548644'%3E%3C/span%3E%3Cscript src='" + cnzz_protocol + "v1.cnzz.com/stat.php%3Fid%3D1278548644%26show%3Dpic1' type='text/javascript'%3E%3C/script%3E"));
        </script> -->
    </p>
</div>
<input type="hidden" id="web_style" value="black">
<input type="hidden" id="valine_appid" value="c994h5wXLa8fSMa424BTyVhs-gzGzoHsz">
<input type="hidden" id="valine_appKey" value="4tFbwCi4sYo3yRFgiNFpQd4N">

<script src="/libs/jquery.min.js"></script>


<script src="/libs/highlight/highlight.pack.js"></script>

<script src='//cdn.jsdelivr.net/npm/valine@1.3.10/dist/Valine.min.js'></script>

<script src="/js/js.js"></script>

<style type="text/css">
.v * {
    color: #698fca;
}

.v .vlist .vcard .vhead .vsys {
    color: #3a3e4a;
}

.v .vlist .vcard .vh .vmeta .vat {
    color: #638fd5;
}

.v .vlist .vcard .vhead .vnick {
    color: #6ba1ff;
}

.v a {
    color: #8696b1;
}

.v .vlist .vcard .vhead .vnick:hover {
    color: #669bfc;
}
</style>
</body>

</html>